home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 May: Tool Chest / Dev.CD May 97 TC.toast / Sample Code / Snippets / Files / CreateDirWCustIcon / CreateDirWCustIcon.c next >
Encoding:
C/C++ Source or Header  |  1996-08-09  |  11.5 KB  |  543 lines  |  [TEXT/CWIE]

  1. /******************************************************************************************
  2. CreateDirWithCustomIcon.c
  3.         
  4. This snippet demonstrates how to create a directory and how to steal a custom
  5. icon from another directory by CatMoving the "Icon\r" file from the other
  6. directory.
  7.     
  8. Written by Virginia (Ginny) McCulloh
  9. Apple Developer Technical Support
  10. August, 1996, Cupertino, CA
  11. Copyright 1996, Apple Computer, Inc.
  12.  
  13. This runs under Metrowerks CodeWarrior 8 with the Universal 
  14. Interfaces 2.1 from ETO #18.
  15. ******************************************************************************************/
  16.  
  17.  
  18. #include <StandardFile.h>
  19. #include "CreateDirWCustIcon.h"
  20.  
  21. /*****     Prototypes      *****/
  22. void        main(void);
  23. void         initApp(void);
  24. Boolean        checkGestaltFeatures(void);
  25. Boolean     installAEHandlers();
  26. void         setUpMenus(void);
  27. void         setUpWindow(void);
  28. void         setUpMenus(void);
  29. void         doHighLevel(EventRecord *eventRec);
  30. void         doMousedown(EventRecord *eventRec);
  31. void         doKey(EventRecord *eventRec);
  32. void        doUpdate(EventRecord *eventRec);
  33. void         dispatch(long menuResult);
  34. void         doAppleCmds (short theItem);
  35. void         doFileCmds (short theItem);
  36. void         doTestCmds (short theItem);
  37. void         doTheTest(void);
  38. void         makeCustomIconFolder(FSSpec *iconFileSpec);
  39.  
  40.  
  41. pascal OSErr    DoOpenAppAE(AppleEvent theAppleEvent, AppleEvent reply, long refCon);
  42. pascal OSErr    DoOpenDocAE(AppleEvent theAppleEvent, AppleEvent reply, long refCon);
  43. pascal OSErr    DoPrintDocAE(AppleEvent theAppleEvent, AppleEvent reply, long refCon);
  44. pascal OSErr    DoQuitAppAE(AppleEvent theAppleEvent, AppleEvent reply, long refCon);
  45.  
  46.  
  47. /*****  globals *****/
  48. Boolean                    gQuitTheApp = false;        /* true = quit program */
  49. /*****    main() *****/
  50.  
  51. void main()
  52. {
  53.     short            sleepTime  =  60;
  54.     EventRecord        myEvent;
  55.  
  56.     
  57.     initApp();                                /* call initialization routine */
  58.     setUpMenus();
  59.     do
  60.     {
  61.         if (WaitNextEvent(everyEvent, &myEvent, sleepTime, NIL))
  62.             switch (myEvent.what)
  63.             {
  64.                 case mouseDown:
  65.                     doMousedown(&myEvent);
  66.                     break;
  67.                     
  68.                 case keyDown:
  69.                 case autoKey:
  70.                     doKey(&myEvent);
  71.                     break;
  72.  
  73.                 case kHighLevelEvent:
  74.                     doHighLevel(&myEvent);
  75.                     break;
  76.  
  77.                 case activateEvt:
  78.                     break;
  79.                 
  80.                 case updateEvt:
  81.                     doUpdate(&myEvent);
  82.                     break; 
  83.                 
  84.                 case diskEvt:
  85.                     break;
  86.             
  87.                 case osEvt:                /*  I don't really care yet. */
  88.                     break;
  89.             }
  90.     }  while (!gQuitTheApp);        
  91.     
  92. }                 /* end of main */
  93.  
  94.  
  95. /*****    initApp() *****/
  96.  
  97. void initApp()
  98. {
  99.     
  100.     /* Memory specific initializations. */
  101.     
  102.     MaxApplZone();                /* grow the heap to its maximum size */
  103.     MoreMasters();                   /* create more master pointers         */
  104.     MoreMasters();
  105.     MoreMasters();
  106.     MoreMasters();
  107.     MoreMasters();
  108.  
  109.     /* Initializing the ROM Managers */
  110.     
  111.     InitGraf((Ptr) &qd.thePort);
  112.     InitFonts();
  113.     InitWindows();
  114.     InitMenus();
  115.     FlushEvents(everyEvent,0);
  116.     TEInit();
  117.     InitDialogs(NIL);
  118.     InitCursor();
  119.     
  120.     if (!checkGestaltFeatures())
  121.         ExitToShell();
  122.     
  123.     /* Install the required Apple Event Handlers */
  124.     if (!installAEHandlers())
  125.         ExitToShell();
  126. }                /* end of initApp() */
  127.  
  128.  
  129.  
  130. /*****  checkGestaltFeatures() *****/
  131. Boolean checkGestaltFeatures()
  132. {
  133.     long        gestaltFeature;
  134.     OSErr        myErr;
  135.  
  136.     myErr = Gestalt(gestaltSystemVersion, &gestaltFeature);     /* which SysVersion present? */
  137.     if (myErr == noErr)
  138.     {
  139.         gestaltFeature = (gestaltFeature >> 8) & 0xf; 
  140.                                         /* shift result over & mask out major version number */
  141.         if (gestaltFeature < 7)         /* This is a System 7+ shell.  We quit otherwise. */
  142.         {
  143.             StopAlert(BADSYSTEMID, nil);
  144.             return(false);
  145.         }
  146.     }
  147.     
  148.     if (myErr == noErr)
  149.     {
  150.         myErr = Gestalt(gestaltQuickdrawVersion, &gestaltFeature);
  151.                                                     /* we want color QD cuz we're spoiled */
  152.         if (myErr == noErr)
  153.         {
  154.             if(gestaltFeature < gestalt32BitQD)
  155.             {
  156.                 StopAlert(BADQUICKDRAWID, nil);
  157.                 return(false);
  158.             }
  159.         }
  160.     }
  161.     
  162.     
  163.     
  164.     if (myErr == noErr)
  165.     {
  166.         myErr = Gestalt(gestaltAppleEventsAttr, &gestaltFeature);
  167.         if (myErr == noErr)
  168.         {
  169.             if (!(gestaltFeature & 0xf))
  170.             {
  171.                 StopAlert(NOAPPLEEVENTS, nil);
  172.                 return(false);
  173.             }
  174.         }
  175.     }
  176.     if (!myErr)        
  177.         return(true);            /* if there was an error we cannot continue */
  178.     else
  179.     {
  180.         return(false);            /* we made it through without a hitch */
  181.     }
  182. }
  183.  
  184. /*****    installAEHandlers *****/
  185. Boolean installAEHandlers()
  186. {
  187.     OSErr        myErr;
  188.     
  189.     myErr = AEInstallEventHandler ( kCoreEventClass, 
  190.                     kAEOpenApplication, NewAEEventHandlerProc(DoOpenAppAE), 0L, false );
  191.     if (myErr == noErr)
  192.         myErr = AEInstallEventHandler ( kCoreEventClass,
  193.                     kAEOpenDocuments, NewAEEventHandlerProc(DoOpenDocAE), 0L, false );
  194.     if (myErr == noErr)
  195.         myErr = AEInstallEventHandler ( kCoreEventClass,
  196.                     kAEPrintDocuments, NewAEEventHandlerProc(DoPrintDocAE), 0L, false );
  197.     if (myErr == noErr)
  198.         myErr = AEInstallEventHandler ( kCoreEventClass,
  199.                     kAEQuitApplication, NewAEEventHandlerProc(DoQuitAppAE), 0L, false );
  200.     if (myErr)
  201.         return(false);
  202.     else
  203.         return(true);
  204. }
  205.  
  206. /*****    setUpMenus() 
  207.             This will put up our menus.  Be sure to read the comments by the
  208.             AppendMenu() and SetItem() calls to see how different options
  209.             behave.        
  210. *****/
  211. void setUpMenus()
  212. {
  213.     short            n;
  214.     MenuHandle        theMenu;
  215.     
  216.     for (n = 0; n < MAXMENUS; n++)
  217.     {
  218.         theMenu = GetMenu(FIRSTMENUID + n);
  219.         if (theMenu)                  
  220.             InsertMenu(theMenu, 0);
  221.     }
  222.  
  223.     theMenu = GetMHandle(APPLEMENU);
  224.     if (theMenu)
  225.         AddResMenu(theMenu, 'DRVR');
  226.     
  227.     DrawMenuBar();
  228.     return;
  229. }                    /* end of setUpMenus()  */
  230.  
  231. /*****    setUpWindow() *****/
  232.  
  233. void setUpWindow( void )
  234. {
  235.     WindowPtr    myWind;
  236.  
  237.     myWind = GetNewCWindow(WINDOWID, nil, PUTINFRONT);
  238.     if (myWind != nil)
  239.     {
  240.         ShowWindow(myWind);
  241.     }
  242. }
  243.  
  244.  
  245. /*****    doMousedown()
  246.             We figure out where the user has clicked the mouse.  If the user
  247.             clicks anywhere but the menu bar, we beep.  Otherwise, we figure
  248.             out which menu they have clicked and dispatch.
  249. *****/
  250. void doMousedown(EventRecord *eventRec)
  251. {
  252.     short        windPart;
  253.     WindowPtr    myWind;
  254.     long        menuResult;
  255.     
  256.     windPart = FindWindow(eventRec->where, &myWind);
  257.     
  258.     switch(windPart)
  259.     {
  260.         case inContent:
  261.             SelectWindow(myWind);
  262.             break;
  263.  
  264.         case inDrag:
  265.             DragWindow( myWind, eventRec->where, &qd.screenBits.bounds );
  266.             break;
  267.  
  268.         case inMenuBar:
  269.             menuResult = MenuSelect(eventRec->where);
  270.             dispatch(menuResult);
  271.             break;
  272.  
  273.         case inSysWindow:
  274.             SystemClick( eventRec, myWind );
  275.             break;
  276.             
  277.         case inGoAway:
  278.             gQuitTheApp = true;
  279.             break;
  280.             
  281.         default:
  282.             break;
  283.     }
  284.     return;
  285. }                 /* end of doMousedown */
  286.  
  287.  
  288. /*****     doKey()
  289.             We ignore keys pressed unless they are accompanied by a 
  290.             command key.  Then we dispatch.
  291. *****/
  292. void doKey(EventRecord *eventRec)
  293. {
  294.     char    keyPressed;
  295.     long    menuResult;
  296.     
  297.     keyPressed = (char) (eventRec->message & charCodeMask);
  298.     
  299.     if((eventRec->modifiers & cmdKey) != 0)
  300.     {
  301.         menuResult = MenuKey(keyPressed);
  302.         dispatch(menuResult);    
  303.     }
  304.     return;
  305. }                 /* end of do_key */
  306.  
  307.  
  308. /*****    doHighLevel() *****/
  309. void doHighLevel(EventRecord *eventRec)
  310. {
  311.     OSErr myErr;
  312.     myErr = AEProcessAppleEvent(eventRec);
  313. }
  314.  
  315.  
  316. pascal OSErr    DoOpenAppAE(AppleEvent theAppleEvent, AppleEvent reply, long refCon)
  317. {
  318.     #pragma unused(theAppleEvent, reply, refCon)
  319.     
  320.     setUpWindow();
  321.     return(noErr);
  322. }
  323. pascal OSErr    DoOpenDocAE(AppleEvent theAppleEvent, AppleEvent reply, long refCon)
  324. {
  325.     #pragma unused(theAppleEvent, reply, refCon)
  326.     
  327.     return(noErr);
  328. }
  329. pascal OSErr    DoPrintDocAE(AppleEvent theAppleEvent, AppleEvent reply, long refCon)
  330. {
  331.     #pragma unused(theAppleEvent, reply, refCon)
  332.     
  333.     return(noErr);
  334. }
  335. pascal OSErr    DoQuitAppAE(AppleEvent theAppleEvent, AppleEvent reply, long refCon)
  336. {
  337.     #pragma unused(theAppleEvent, reply, refCon)
  338.     
  339.     gQuitTheApp = true;
  340.     return(noErr);
  341. }
  342.  
  343.  
  344. /***** doUpdate() *****/
  345. void    doUpdate(EventRecord *eventRec)
  346. {
  347.     GrafPtr        savedPort;
  348.     WindowPtr    theWindow;
  349.     theWindow = (WindowPtr) eventRec->message;
  350.     
  351.     GetPort(&savedPort);
  352.     SetPort((GrafPtr) theWindow);
  353.     BeginUpdate(theWindow);
  354.     EndUpdate(theWindow);
  355.     SetPort(savedPort);
  356. }
  357.  
  358.  
  359. /*****     dispatch()
  360.             We determine which menu the user has chosen (either with mouse
  361.             or with command keys) and jump to the routine that handles
  362.             that menu's commands.
  363. *****/
  364. void dispatch(long menuResult)
  365. {
  366.     short        theMenu;            /* menu selected */
  367.     short        theItem;            /* item selected */
  368.     
  369.     theMenu = HiWord (menuResult);        /* menuID selected */
  370.     theItem = LoWord (menuResult);        /* item# selected */
  371.     
  372.     switch (theMenu)
  373.     {
  374.         case APPLEMENU:
  375.             doAppleCmds(theItem);
  376.             break;
  377.  
  378.         case FILEMENU:
  379.             doFileCmds(theItem);
  380.             break;
  381.             
  382.         case EDITMENU:
  383.             break;
  384.  
  385.         case TESTMENU:
  386.             doTestCmds(theItem);
  387.             break;
  388.     }
  389.     HiliteMenu(0);
  390. }                /* end of dispatch */
  391.  
  392.  
  393.  
  394. /*****     doAppleCmds() 
  395.             When the user chooses the "About MyMenuText" item, we display the
  396.             About box.  If the user chooses a DA, we open the DA.
  397. *****/
  398. void doAppleCmds(short theItem)
  399. {    
  400.     MenuHandle        myMenu;
  401.     Str255            name;
  402.     short            dummy;
  403.     
  404.     if(theItem == appleABOUT)
  405.     {
  406.         Alert(ABOUTID, (ModalFilterUPP) NIL);
  407.     }
  408.     else
  409.     {
  410.         myMenu = GetMHandle (APPLEMENU);
  411.         if (myMenu)
  412.         {
  413.             GetItem(myMenu, theItem, name);
  414.             dummy = OpenDeskAcc(name);
  415.         }
  416.     }
  417.     return;
  418. }                 /* end of doAppleCmds */
  419.  
  420.  
  421.  
  422. /*****    doFileCmds() 
  423.             When the user chooses Quit on the File menu, we quit.
  424. *****/
  425. void doFileCmds (short theItem)
  426. {
  427.     switch (theItem)
  428.     {            
  429.         case fileQUIT:
  430.             gQuitTheApp = true;
  431.             break;
  432.     }
  433.     return;
  434. } /* end of doFileCmds */
  435.  
  436.  
  437.  
  438. /*****    doTestCmds()
  439.             When the user chooses the item in the Test menu, they
  440.             will get to choose a folder with a custom icon
  441. *****/
  442. void doTestCmds (short theItem)
  443. {    
  444.     StandardFileReply    reply;
  445.     FSSpec                spec;
  446.     OSErr                err;
  447.     
  448.     switch (theItem)
  449.     {
  450.         case testDOTHETEST:
  451.             //open a folder with a custom icon and choose the "Icon\r" file
  452.             StandardGetFile(nil, -1, nil, &reply);
  453.             
  454.             if (reply.sfGood)
  455.             {
  456.                 //make an FSSpec to the "Icon\r" file
  457.                 err = FSMakeFSSpec(reply.sfFile.vRefNum, reply.sfFile.parID, 
  458.                                     reply.sfFile.name, &spec);
  459.                 if (!err)
  460.                     makeCustomIconFolder(&spec);
  461.             }
  462.             break;            
  463.     }    
  464.     return;
  465. }                /* end of doTestCmds */
  466.  
  467. #define        HAS_CUST_ICON    0x0400
  468. #define     HAS_BEEN_INIT     0x0100
  469.  
  470. void makeCustomIconFolder(FSSpec *iconFileSpec)
  471. {
  472.     OSErr        err;
  473.     FSSpec        foldSpec;
  474.     long        dirID;
  475.     CInfoPBRec    pb;
  476.  
  477.     /*    
  478.         Make an FSSpec for the directory we're creating
  479.         For demo purposes, we'll put this in the root directory
  480.         of the boot volume.
  481.     */
  482.     err = FSMakeFSSpec(-1, fsRtDirID, "\pNew Folder", &foldSpec);
  483.     
  484.     /* Since the folder doesn't exist, we should get fnfErr */
  485.     if (err == fnfErr)
  486.     {
  487.         //create the the directory
  488.         err = FSpDirCreate(&foldSpec, smSystemScript, &dirID);
  489.             
  490.         if (!err)
  491.         {
  492.             pb.dirInfo.ioCompletion = nil;
  493.             pb.dirInfo.ioNamePtr = "\pNew Folder"; // we care about file names
  494.             pb.dirInfo.ioVRefNum = foldSpec.vRefNum;
  495.             pb.dirInfo.ioFDirIndex = 0;    // use ioNamePtr
  496.             pb.dirInfo.ioDrDirID = foldSpec.parID;
  497.             
  498.             err = PBGetCatInfoSync(&pb);
  499.             
  500.             //set the custom icon flag bit in the DInfo record for the new folder
  501.             if (!err)
  502.             {
  503.                 if ( (pb.dirInfo.ioDrUsrWds.frFlags & HAS_CUST_ICON) == 0)
  504.                 {
  505.                     pb.dirInfo.ioDrUsrWds.frFlags |= HAS_CUST_ICON;  
  506.                         /* turn this bit on  */
  507.                     pb.dirInfo.ioDrUsrWds.frFlags &= ~HAS_BEEN_INIT; 
  508.                         /* turn this bit off */
  509.                 }
  510.  
  511.                 /*
  512.                     PBGetCatInfo messes up the dirID field in parameter block
  513.                     so we have to reset it.
  514.                 */
  515.                 pb.dirInfo.ioDrDirID = foldSpec.parID;
  516.                 err = PBSetCatInfoSync(&pb);    // set the hasCustomIcon flag
  517.                 
  518.                 //Move the icon file into the new folder
  519.                 if (!err)
  520.                 {
  521.                     /*
  522.                         Move our invisible Icon file ("\pIcon\r")
  523.                         into our new folder.
  524.                     */
  525.                     err = FSpCatMove(iconFileSpec, &foldSpec);
  526.                     
  527.                     if (!err)
  528.                     {
  529.                         /* 
  530.                             Do a Mod Date Bump to get Finder to update cache
  531.                             Note:  Because the Finder caches information about
  532.                             open windows, you might need to use the BumpDate
  533.                             routine from MoreFiles
  534.                         */
  535.                     }
  536.                 }
  537.             }
  538.         }
  539.  
  540.     }
  541.     
  542.     return;
  543. }